package gui.frame;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

class Display {
	public static final int EVENT = 0, COMPONENT = 1, MOUSE = 2,
			MOUSE_MOVE = 3, FOCUS = 4, KEY = 5, ACTION = 6, LAST = 7;

	public String[] evt;

	Display() {
		evt = new String[Display.LAST];
		for (int i = 0; i < Display.LAST; i++) {
			evt[i] = new String();
		}
	}

	public void show(Graphics g) {
		for (int i = 0; i < Display.LAST; i++) {
			g.drawString(evt[i], 0, 10 * i + 10);
		}
	}
}

class EnablePanel extends Panel {
	Color c;
	int id;
	Display display = new Display();

	EnablePanel(int i, Color mc) {
		id = i;
		c = mc;
		this.setLayout(new BorderLayout());
		this.add(new myButton(), BorderLayout.SOUTH);
		this.addFocusListener(new FL());
		this.addKeyListener(new KL());
		this.addComponentListener(new CL());
		this.addMouseListener(new ML());
		this.addMouseMotionListener(new MML());
	}

	public void update(Graphics g) {
		paint(g);
	}

	public void paint(Graphics g) {
		g.setColor(c);
		Dimension s = getSize();
		g.fillRect(0, 0, s.width, s.height);
		g.setColor(Color.black);
		display.show(g);
	}

	public void processEvent(AWTEvent e) {
		display.evt[Display.EVENT] = e.toString();
		repaint();
		super.processEvent(e);
	}

	class CL implements ComponentListener {

		@Override
		public void componentResized(ComponentEvent e) {
			display.evt[Display.COMPONENT] = "Component resized";
			repaint();
		}

		@Override
		public void componentMoved(ComponentEvent e) {
			display.evt[Display.COMPONENT] = "Component moved";
			repaint();
		}

		@Override
		public void componentShown(ComponentEvent e) {
			display.evt[Display.COMPONENT] = "Component shown";
			repaint();
		}

		@Override
		public void componentHidden(ComponentEvent e) {
			display.evt[Display.COMPONENT] = "Component hidden";
			repaint();
		}

	}
	
	class FL implements FocusListener{

		@Override
		public void focusGained(FocusEvent e) {
			display.evt[Display.FOCUS]="Focus gained";
			repaint();
		}

		@Override
		public void focusLost(FocusEvent e) {
			display.evt[Display.FOCUS]="Focus lost";
			repaint();
		}
		
	}
	
	class KL implements KeyListener{

		@Override
		public void keyTyped(KeyEvent e) {
			display.evt[Display.KEY]="KEY typed";
			repaint();
		}

		@Override
		public void keyPressed(KeyEvent e) {
			display.evt[Display.KEY]="KEY pressed";
			repaint();
		}

		@Override
		public void keyReleased(KeyEvent e) {
			display.evt[Display.KEY]="KEY released";
			repaint();
		}
		
	}
	class ML implements MouseListener{
		
		void showMouse(MouseEvent e){
			display.evt[Display.MOUSE]+=",x="+e.getX()+",y="+e.getY();
			repaint();
		}

		@Override
		public void mouseClicked(MouseEvent e) {
			requestFocus();
			display.evt[Display.MOUSE]="Mouse clicked";
			showMouse(e);
		}

		@Override
		public void mousePressed(MouseEvent e) {
			display.evt[Display.MOUSE]="Mouse Pressed";
			showMouse(e);
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			display.evt[Display.MOUSE]="Mouse Released";
			showMouse(e);
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			display.evt[Display.MOUSE]="Mouse Entered";
			showMouse(e);
		}

		@Override
		public void mouseExited(MouseEvent e) {
			display.evt[Display.MOUSE]="Mouse Exited";
			showMouse(e);
		}
		
		
	}
	
	class MML implements MouseMotionListener{

		void showMouse(MouseEvent e){
			display.evt[Display.MOUSE]+=",x="+e.getX()+",y="+e.getY();
			repaint();
		}

		@Override
		public void mouseDragged(MouseEvent e) {
			display.evt[Display.MOUSE_MOVE]="MOUSE dragged";
			showMouse(e);
		}

		@Override
		public void mouseMoved(MouseEvent e) {
			display.evt[Display.MOUSE_MOVE]="MOUSE moved";
			showMouse(e);
		}
		
	}
	
	class myButton extends Button{
		int clickCounter;
		String label="";
		myButton(){
			addActionListener(new AL());
		}
		
		public void paint(Graphics g){
			g.setColor(Color.green);
			Dimension s=getSize();
			g.fillRect(0, 0, s.width-1, s.height);
			g.setColor(Color.black);
			g.drawRect(0, 0, s.width-1, s.height-1);
			drawLabel(g);
		}

		private void drawLabel(Graphics g) {
			FontMetrics fm=g.getFontMetrics();
			int width=fm.stringWidth(label);
			int height=fm.getHeight();
			int ascent=fm.getAscent();
			int leading=fm.getLeading();
			int horizMargin=(getSize().width-width)/2;
			int verMargin=(getSize().height-height)/2;
			
			g.setColor(Color.red);
			g.drawString(label, horizMargin, horizMargin+ascent+leading);
		}
		
		class AL implements ActionListener{

			@Override
			public void actionPerformed(ActionEvent e) {
				clickCounter++;
				label="click#"+clickCounter+" "+e.toString();
				repaint();
			}
			
		}
	}
}

public class FrameTech extends Frame {

	FrameTech() {
		this.setLayout(new GridLayout(2, 2));
		this.add(new EnablePanel(1,Color.cyan));
		this.add(new EnablePanel(2,Color.lightGray));
		this.add(new EnablePanel(3,Color.yellow));
	}
	
	public static void main(String[] args){
		Frame frame=new FrameTech();
		frame.setTitle("Good Tech");
		frame.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				System.out.println(e);
				System.out.println("Window Closing");
				System.exit(0);
			}
		});
		
		frame.setSize(700, 700);
		frame.setVisible(true);
	}
}
